home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
math
/
differ.zip
/
DIFFEREN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-11
|
18KB
|
516 lines
#include "differ.h"
/*
Copytree is useful to well copy trees !
It takes an expression and makes another copy of it.
*/
struct expression *copytree(struct expression *expr)
{ struct expression *coptree;
if (expr==NULL) return NULL;
coptree=newtree();
coptree->expval=expr->expval;
coptree->exptype=expr->exptype;
switch(coptree->exptype)
{ case OPERATOR: coptree->expval.op=expr->expval.op;
break;
case VALUE: coptree->cval=expr->cval;
break;
case CONSTANT: coptree->expval.co=expr->expval.co;
break;
case FUNCTION: coptree->expval.fn=expr->expval.fn;
break;
case X:
case UNDEF_ETYPE:
default:;
}
coptree->lval=copytree(expr->lval);
coptree->rval=copytree(expr->rval);
return coptree;
}
/*
This routine is one of the workhorses of the program. It takes an
expression tree and differentiates it. Note that we must take of
differentiating f1(x) ^ f2(x) say and not just f1(x) ^ n.
This is one of the reasons why it is so complicated and simplifying
will be necessary to get of extraneous bits. As it stands now it can
differentiate most things.
I never got round to adding ARCCOT,ARCSEC,ARCCOSEC and the associated
hyperbolic functions, but at the same time I haven't actually seen any
problems with these in. Just about every other trig/hyp function is
there though. Of course it supports functions of functions etc.
*/
struct expression *differentiate(struct expression *expr)
{ struct expression *temptree,
*dtree;
if(expr==NULL) return NULL;
switch(expr->exptype)
{ case OPERATOR: switch(expr->expval.op)
{ case MINUS:
case PLUS: expr->lval=differentiate(expr->lval);
expr->rval=differentiate(expr->rval);
return expr;
case TIMES: expr->expval.op=PLUS;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr->lval;
expr->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr->rval;
expr->rval=temptree;
expr->lval->rval=differentiate(copytree(expr->rval->lval));
expr->rval->rval=differentiate(copytree(expr->lval->lval));
return expr;
case DIVIDE: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr->rval;
temptree->rval=copytree(temptree->lval);
expr->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=MINUS;
temptree->rval=expr->lval;
expr->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr->lval->rval;
expr->lval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=copytree(expr->rval->rval);
expr->lval->lval=temptree;
expr->lval->lval->rval=differentiate(copytree(expr->lval->rval->lval));
expr->lval->rval->rval=differentiate(copytree(expr->rval->rval));
return expr;
case POWER: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=PLUS;
expr->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
expr->lval->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
expr->lval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=DIVIDE;
expr->lval->rval->rval=temptree;
temptree=newtree();
temptree->exptype=FUNCTION;
temptree->expval.op=LN;
expr->lval->lval->rval=temptree;
expr->lval->lval->rval->rval=copytree(expr->rval->lval);
expr->lval->rval->rval->rval=copytree(expr->rval->lval);
expr->lval->rval->rval->lval=copytree(expr->rval->rval);
expr->lval->lval->lval=differentiate(copytree(expr->rval->rval));
expr->lval->rval->lval=differentiate(copytree(expr->rval->lval));
return expr;
case UMINUS: expr->rval=differentiate(expr->rval);
return expr;
case UNDEF_OP:
default: printf("undefined operator in expression\n\r");
return expr;
}
case VALUE: expr->cval=0;
return expr;
case CONSTANT: expr->exptype=VALUE;
expr->cval=0;
return expr;
case X: expr->exptype=VALUE;
expr->cval=1;
return expr;
case FUNCTION: switch(expr->expval.fn)
{ case SIN: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr->expval.fn=COS;
temptree->lval=differentiate(copytree(expr->rval));
return temptree;
case EXP: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
temptree->lval=differentiate(copytree(expr->rval));
return temptree;
case LN: expr->exptype=OPERATOR;
expr->expval.op=DIVIDE;
expr->lval=differentiate(copytree(expr->rval));
return expr;
case COS: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr->expval.fn=SIN;
expr=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=expr;
expr=temptree;
expr->rval->lval=differentiate(copytree(expr->rval->rval->rval));
return expr;
case TAN: expr->expval.fn=SEC;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
temptree->lval=expr;
expr=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
expr->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
return expr;
case SEC: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr;
temptree->rval=copytree(expr);
temptree->rval->expval.fn=TAN;
expr=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
return expr;
case COSEC: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr;
temptree->rval=copytree(expr);
temptree->rval->expval.fn=COT;
expr=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=expr;
return temptree;
case COT: expr->expval.fn=COSEC;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
temptree->lval=expr;
expr=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
expr->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=expr;
return temptree;
case SINH: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr->expval.fn=COSH;
temptree->lval=differentiate(copytree(expr->rval));
return temptree;
case COSH: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr->expval.fn=SINH;
temptree->lval=differentiate(copytree(expr->rval));
return temptree;
case TANH: expr->expval.fn=SECH;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
temptree->lval=expr;
expr=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
expr->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
return expr;
case SECH: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr;
temptree->rval=copytree(expr);
temptree->rval->expval.fn=TANH;
expr=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=expr;
return temptree;
case COTH: expr->expval.fn=COSECH;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
temptree->lval=expr;
expr=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
expr->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=expr;
return temptree;
case COSECH: temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->lval=expr;
temptree->rval=copytree(expr);
temptree->rval->expval.fn=COTH;
expr=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=TIMES;
temptree->rval=expr;
expr=temptree;
expr->lval=differentiate(copytree(expr->rval->lval->rval));
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=expr;
return temptree;
case ARCSIN: dtree=newtree();
dtree->exptype=OPERATOR;
dtree->expval.op=DIVIDE;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=0.5;
dtree->rval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=MINUS;
dtree->rval->lval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=1;
dtree->rval->lval->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval->lval->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
dtree->rval->lval->rval->rval=temptree;
dtree->rval->lval->rval->lval=expr->rval;
dtree->lval=differentiate(copytree(expr->rval));
expr->rval=NULL;
freetree(expr);
return dtree;
case ARCCOS: dtree=newtree();
dtree->exptype=OPERATOR;
dtree->expval.op=DIVIDE;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=0.5;
dtree->rval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=MINUS;
dtree->rval->lval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=1;
dtree->rval->lval->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval->lval->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
dtree->rval->lval->rval->rval=temptree;
dtree->rval->lval->rval->lval=expr->rval;
dtree->lval=differentiate(copytree(expr->rval));
expr->rval=NULL;
freetree(expr);
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=UMINUS;
temptree->rval=dtree;
return temptree;
case ARCTAN: dtree=newtree();
dtree->exptype=OPERATOR;
dtree->expval.op=DIVIDE;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=PLUS;
dtree->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=1;
dtree->rval->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
dtree->rval->rval->rval=temptree;
dtree->rval->rval->lval=expr->rval;
dtree->lval=differentiate(copytree(expr->rval));
expr->rval=NULL;
freetree(expr);
return dtree;
case ARCSINH: dtree=newtree();
dtree->exptype=OPERATOR;
dtree->expval.op=DIVIDE;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=0.5;
dtree->rval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=PLUS;
dtree->rval->lval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=1;
dtree->rval->lval->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval->lval->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
dtree->rval->lval->rval->rval=temptree;
dtree->rval->lval->rval->lval=expr->rval;
dtree->lval=differentiate(copytree(expr->rval));
expr->rval=NULL;
freetree(expr);
return dtree;
case ARCCOSH: dtree=newtree();
dtree->exptype=OPERATOR;
dtree->expval.op=DIVIDE;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=0.5;
dtree->rval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=MINUS;
dtree->rval->lval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=1;
dtree->rval->lval->rval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval->lval->lval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
dtree->rval->lval->lval->rval=temptree;
dtree->rval->lval->lval->lval=expr->rval;
dtree->lval=differentiate(copytree(expr->rval));
expr->rval=NULL;
freetree(expr);
return dtree;
case ARCTANH: dtree=newtree();
dtree->exptype=OPERATOR;
dtree->expval.op=DIVIDE;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=MINUS;
dtree->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=1;
dtree->rval->lval=temptree;
temptree=newtree();
temptree->exptype=OPERATOR;
temptree->expval.op=POWER;
dtree->rval->rval=temptree;
temptree=newtree();
temptree->exptype=VALUE;
temptree->cval=2;
dtree->rval->rval->rval=temptree;
dtree->rval->rval->lval=expr->rval;
dtree->lval=differentiate(copytree(expr->rval));
expr->rval=NULL;
freetree(expr);
return dtree;
case UNDEF_FUNC:
default: printf("Undefined function in expression\n\r");
return expr;
}
case UNDEF_ETYPE:
default: printf("Undefined type in expression\n\r");
return expr;
}
}